﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace dnFileEncryptor
{
	public partial class EncryptDecrypt : Form
	{
		public EncryptDecrypt(string filePath)
		{
			InitializeComponent();
			tbFilePath.Text = filePath;
			loadSettings();
			updateState();
		}

		public EncryptDecrypt() : this("")
		{
		}

		private EncryptionAlgorithmType activeAlgorithm = EncryptionAlgorithmType.AES;

		public EncryptionAlgorithmType ActiveAlgorithm
		{
			get { return activeAlgorithm; }
			set { activeAlgorithm = value; updateState(); }
		}

		private void updateState()
		{
			if (tbPassword1.Text.Trim() != "" &&
				tbPassword1.Text == tbPassword2.Text &&
				tbFilePath.Text.Trim() != "" &&
				File.Exists(tbFilePath.Text))
			{
				btnEncrypt.Enabled = true;
				btnDecrypt.Enabled = true;
			}
			else
			{
				btnEncrypt.Enabled = false;
				btnDecrypt.Enabled = false;
			}

			aESToolStripMenuItem.Checked = false;
			trippleDESToolStripMenuItem.Checked = false;
			dESToolStripMenuItem.Checked = false;
			if (activeAlgorithm == EncryptionAlgorithmType.AES) 
			{
				aESToolStripMenuItem.Checked = true;
			}
			else if (activeAlgorithm == EncryptionAlgorithmType.DES)
			{
				dESToolStripMenuItem.Checked = true;
			}
			else
			{
				trippleDESToolStripMenuItem.Checked = true;
			}

			if (Properties.Settings.Default.FileExtension != null &&
				Properties.Settings.Default.FileExtension.Trim() != "")
			{
				if (tbFilePath.Text.EndsWith("." + Properties.Settings.Default.FileExtension))
				{
					this.AcceptButton = btnDecrypt;
				}
				else
				{
					this.AcceptButton = btnEncrypt;
				}
			}
		}

		private void loadSettings()
		{
			ActiveAlgorithm = EnumValues.ParseEnum<EncryptionAlgorithmType>(Properties.Settings.Default.EncryptionAlgorithm, 
				Constants.EncryptionAlgorithm);			
		}

		private void saveSettings()
		{
			Properties.Settings.Default.EncryptionAlgorithm = Enum.GetName(typeof(EncryptionAlgorithmType), ActiveAlgorithm);
			Properties.Settings.Default.Save();
		}

		private void btnBrowse_Click(object sender, EventArgs e)
		{
			openFileDialog.FileName = tbFilePath.Text;
			if (openFileDialog.ShowDialog() == DialogResult.OK)
			{
				tbFilePath.Text = openFileDialog.FileName;
			}
		}

		private void btnEncrypt_Click(object sender, EventArgs e)
		{
			if (tbPassword1.Text == tbPassword2.Text)
			{
				if (Properties.Settings.Default.FileExtension != null &&
					Properties.Settings.Default.FileExtension.Trim() != "")
				{
					saveFileDialog.DefaultExt = Properties.Settings.Default.FileExtension;
					saveFileDialog.FileName = tbFilePath.Text + "." + Properties.Settings.Default.FileExtension;
				}
				else
				{
					saveFileDialog.FileName = tbFilePath.Text + ".enc";
				}
				if (saveFileDialog.ShowDialog() == DialogResult.OK)
				{
					try
					{
						Core.EncryptFile(tbFilePath.Text, saveFileDialog.FileName, ActiveAlgorithm, tbPassword1.Text);
						MessageBox.Show("File successfully encrypted.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
					}
					catch (Exception ex)
					{
						MessageBox.Show("Encryption failed. " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
					}
				}
			}
		}

		private void btnDecrypt_Click(object sender, EventArgs e)
		{
			if (tbPassword1.Text == tbPassword2.Text)
			{
				if (Properties.Settings.Default.FileExtension != null &&
					Properties.Settings.Default.FileExtension.Trim() != "" &&
					tbFilePath.Text.EndsWith(Properties.Settings.Default.FileExtension))
				{
					saveFileDialog.FileName = tbFilePath.Text.Substring(0, tbFilePath.Text.Length - Properties.Settings.Default.FileExtension.Length - 1);
				} else {
					saveFileDialog.FileName = tbFilePath.Text;
				}
				if (saveFileDialog.ShowDialog() == DialogResult.OK)
				{
					try
					{
						Core.DecryptFile(tbFilePath.Text, saveFileDialog.FileName, ActiveAlgorithm, tbPassword1.Text);
						MessageBox.Show("File successfully decrypted.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
					}
					catch (Exception ex)
					{
						if (ex.Message == "Padding is invalid and cannot be removed.")
							MessageBox.Show("Decryption failed. Invalid key.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
						else
							MessageBox.Show("Decryption failed. " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
					}
				}
			}
		}

		private void tbPassword_TextChanged(object sender, EventArgs e)
		{
			updateState();
			double passStrength = Core.GetPasswordComplexity(tbPassword1.Text);
			string strStrength = "weak;";

			if (passStrength <= 32)
			{
				strStrength = "weak;";
			}
			else if (passStrength <= 64)
			{
				strStrength = "mediocre;";
			}
			else if (passStrength <= 128)
			{
				strStrength = "OK;";
			}
			else if (passStrength > 128)
			{
				strStrength = "great;";
			}

			lblPasswordStrength.Text = "Your password is " + strStrength +
				" equivalent to a " + Math.Round(passStrength, 0) + "-bit key.";
		}

		private void EncryptDecrypt_FormClosing(object sender, FormClosingEventArgs e)
		{
			saveSettings();
		}

		private void menuItem_Click(object sender, EventArgs e)
		{
			if (sender == aESToolStripMenuItem)
				activeAlgorithm = EncryptionAlgorithmType.AES;
			else if (sender == trippleDESToolStripMenuItem)
				activeAlgorithm = EncryptionAlgorithmType.TDES;
			else
				activeAlgorithm = EncryptionAlgorithmType.DES;
			updateState();
		}

		private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
		{
			OptionsForm form = new OptionsForm();
			form.ShowDialog();
		}

		private void tbFilePath_TextChanged(object sender, EventArgs e)
		{
			updateState();
			tbPassword1.Select();
		}

		private void formKeyDown(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Escape)
				Close();
		}

		private void btnClose_Click(object sender, EventArgs e)
		{
			Close();
		}
	}
}
